#include "PolygonFactory.h"

using namespace model;

PolygonFactory& PolygonFactory::instance()
{
	static PolygonFactory instance;
	return instance;
}

Polygon* PolygonFactory::createSquare(const Point &position, Polygon::PolygonOrigin positionLocation, int size)
{
	return createRectangle(position, positionLocation, size, size);
}

Polygon* PolygonFactory::createRectangle(const Point &position, Polygon::PolygonOrigin positionLocation, int width, int height)
{
	Point topLeft, topRight, bottomLeft, bottomRight;	
	
	if (positionLocation == Polygon::P_Center)
	{
		topLeft     = Point(position.x() - width/2, position.y() - height/2);
		topRight    = Point(position.x() + width/2, position.y() - height/2);
		bottomLeft  = Point(position.x() - width/2, position.y() + height/2);
		bottomRight = Point(position.x() + width/2, position.y() + height/2);
	}
	else if (positionLocation == Polygon::P_TopLeft)
	{
		topLeft     = Point(position.x(), position.y());
		topRight    = Point(position.x() + width, position.y());
		bottomLeft  = Point(position.x(), position.y() + height);
		bottomRight = Point(position.x() + width, position.y() + height);
	}

	Polygon *p = new Polygon(positionLocation);
	p->addVertex(topLeft);
	p->addVertex(topRight);
	p->addVertex(bottomRight);
	p->addVertex(bottomLeft);
	return p;
}

Polygon* PolygonFactory::createTriangle(const Point &position, Polygon::PolygonOrigin positionLocation, int width, int height)
{
	Point leftCorner, topCorner, rightcorner;
	
	if (positionLocation == Polygon::P_Center)
	{
		leftCorner  = Point(position.x() - width/2, position.y() + height/2);
		topCorner   = Point(position.x(), position.y() - height/2);
		rightcorner = Point(position.x() + width/2, position.y() + height/2);
	}
	else if (positionLocation == Polygon::P_TopLeft)
	{
		leftCorner   = Point(position.x(), position.y() + height);
		topCorner    = Point(position.x() + width/2, position.y());
		rightcorner  = Point(position.x() + width, position.y() + height);
	}

	Polygon *p = new Polygon(positionLocation);
	p->addVertex(leftCorner);
	p->addVertex(topCorner);
	p->addVertex(rightcorner);
	return p;
}

Polygon* PolygonFactory::createCircle(const Point &position, Polygon::PolygonOrigin positionLocation, int size, int vertices)
{
	Point point1, point2, point3, point4, point5, point6, point7, point8;	
	double radio = size/2;
	double dif = radio/1.4142; //diferencia para calcular los vertices de las diagonales

	if (vertices == 8) // el poligono tiene 8 vertices
	{
	    /*            2
	             1        3                  
			
		       8		     4	     Asi estan definidos los 8 vertices del circulo  
				    
         	     7        5
		              6
	    */

		if (positionLocation == Polygon::P_Center)
		{
			point1 = Point(position.x() - dif, position.y() - dif);
			point2 = Point(position.x(), position.y() - radio);
			point3 = Point(position.x() + dif, position.y() - dif);
			point4 = Point(position.x() + radio, position.y());
			point5 = Point(position.x() + dif, position.y() + dif);
			point6 = Point(position.x(), position.y() + radio);
			point7 = Point(position.x() - dif, position.y() + dif);
			point8 = Point(position.x() - radio, position.y());

		}
		else if (positionLocation == Polygon::P_TopLeft)
		{
			point1 = Point(position.x() + radio - dif, position.y() + radio - dif);
			point2 = Point(position.x() + radio, position.y());
			point3 = Point(position.x() + radio + dif, position.y() + radio - dif);
			point4 = Point(position.x() + size, position.y() + radio);
			point5 = Point(position.x() + radio + dif, position.y() + radio + dif);
			point6 = Point(position.x() + radio, position.y() + size);
			point7 = Point(position.x() + radio - dif, position.y() + radio + dif);
			point8 = Point(position.x(), position.y() + radio);
		}

		Polygon *p = new Polygon(positionLocation);
		p->addVertex(point1);
		p->addVertex(point2);
		p->addVertex(point3);
		p->addVertex(point4);
		p->addVertex(point5);
		p->addVertex(point6);
		p->addVertex(point7);
		p->addVertex(point8);
		return p;
	}
	else // el poligono tiene 16 vertices
	{	
		Point point9, point10, point11, point12, point13, point14, point15, point16;
		double difGrande = radio * 0.92; // radio * cos(22.5);
		double difChica = radio * 0.38; // radio * sin(22.5);

		if (positionLocation == Polygon::P_Center)
		{
			point1  = Point(position.x() - dif, position.y() - dif);  
			point2  = Point(position.x() - difChica, position.y() - difGrande);
			point3  = Point(position.x(), position.y() - radio);    
			point4  = Point(position.x() + difChica, position.y() - difGrande);
			point5  = Point(position.x() + dif, position.y() - dif); 
			point6  = Point(position.x() + difGrande, position.y() - difChica);
			point7  = Point(position.x() + radio, position.y()); 
			point8  = Point(position.x() + difGrande, position.y() + difChica);
			point9  = Point(position.x() + dif, position.y() + dif); 
			point10 = Point(position.x() + difChica, position.y() + difGrande);
			point11 = Point(position.x(), position.y() + radio); 
			point12 = Point(position.x() - difChica, position.y() + difGrande);
			point13 = Point(position.x() - dif, position.y() + dif); 
			point14 = Point(position.x() - difGrande, position.y() + difChica);
			point15 = Point(position.x() - radio, position.y()); 
			point16 = Point(position.x() - difGrande, position.y() - difChica);

		}
		else if (positionLocation == Polygon::P_TopLeft)
		{
			point1  = Point(position.x() + radio - dif, position.y() + radio - dif); 
			point2  = Point(position.x() + radio - difChica, position.y() + radio - difGrande);
			point3  = Point(position.x() + radio, position.y());  
			point4  = Point(position.x() + radio + difChica, position.y() + radio - difGrande);
			point5  = Point(position.x() + radio + dif, position.y() + radio - dif); 
			point6  = Point(position.x() + radio + difGrande, position.y() + radio - difChica);
			point7  = Point(position.x() + size, position.y() + radio); 
			point8  = Point(position.x() + radio + difGrande, position.y() + radio + difChica);
			point9  = Point(position.x() + radio + dif, position.y() + radio + dif); 
			point10 = Point(position.x() + radio + difChica, position.y() + radio + difGrande);
			point11 = Point(position.x() + radio, position.y() + size); 
			point12 = Point(position.x() + radio - difChica, position.y() + radio + difGrande);
			point13 = Point(position.x() + radio - dif, position.y() + radio + dif); 
			point14 = Point(position.x() + radio - difGrande, position.y() + radio + difChica);
			point15 = Point(position.x(), position.y() + radio); 
			point16 = Point(position.x() + radio - difGrande, position.y() + radio - difChica);
		}

		Polygon *p = new Polygon(positionLocation);
		p->addVertex(point1);
		p->addVertex(point2);
		p->addVertex(point3);
		p->addVertex(point4);
		p->addVertex(point5);
		p->addVertex(point6);
		p->addVertex(point7);
		p->addVertex(point8);
		p->addVertex(point9);
		p->addVertex(point10);
		p->addVertex(point11);
		p->addVertex(point12);
		p->addVertex(point13);
		p->addVertex(point14);
		p->addVertex(point15);
		p->addVertex(point16);
		return p;
	}	
}

Polygon* PolygonFactory::createL(const Point &position, Polygon::PolygonOrigin positionLocation, int width, int height, int verticalWidth, int horizontalHeight)
{
	/*
	1___2
	|   |
	|   |               De 1 a 2 hay verticalWidth de ancho
	|   |               De 4 a 5 hay horizontalHeight de alto
	|   |3_______4
	|____________|
	6			 5
	*/

	Point point1, point2, point3, point4, point5, point6;
	verticalWidth = width/4;
	horizontalHeight = height/4;
	
	if (positionLocation == Polygon::P_Center)
	{
		point1 = Point(position.x() - width/2, position.y() - height/2);
		point2 = Point(position.x() - width/2 + verticalWidth, position.y() - height/2);
		point3 = Point(position.x() - width/2 + verticalWidth, position.y() + height/2 - horizontalHeight);
		point4 = Point(position.x() + width/2, position.y() + height/2 - horizontalHeight);
		point5 = Point(position.x() + width/2, position.y() + height/2);
		point6 = Point(position.x() - width/2, position.y() + height/2);
	}
	else if (positionLocation == Polygon::P_TopLeft)
	{
		point1 = Point(position.x(), position.y());
		point2 = Point(position.x() + verticalWidth, position.y());
		point3 = Point(position.x() + verticalWidth, position.y() + height - horizontalHeight);
		point4 = Point(position.x() + width, position.y() + height - horizontalHeight);
		point5 = Point(position.x() + width, position.y() + height);
		point6 = Point(position.x(), position.y() + height);
	}

	Polygon *p = new Polygon(positionLocation);
	p->addVertex(point1);
	p->addVertex(point2);
	p->addVertex(point3);
	p->addVertex(point4);
	p->addVertex(point5);
	p->addVertex(point6);
	return p;
}
